#include "OptData.h"
#include "GeneralSetup.h"
#include "anyoption.h"
#include "MDopt.h"
#include "boost/date_time/posix_time/posix_time.hpp"

using namespace std;
using namespace boost::posix_time;

int main(int argc, char* argv[]) {
	AnyOption opt;
	opt.addUsage("");
	opt.addUsage("Usage: ");
	opt.addUsage("--setupFile                       setupFile file");
	opt.setOption("setupFile");
	opt.processCommandArgs(argc, argv);
	string setupFile = "";

	if (opt.getValue("setupFile") != NULL) {
		setupFile = opt.getValue("setupFile");
	} else {
		opt.printUsage();
		return 0;
	}

	GeneralSetup setup;
	setup.parseSetupFile(setupFile);
	
	OptData optData;
	optData.inputDoseSize(setup.dosegridFile);   // input the size of dose matrix

	for(int indexField=0;indexField<setup.fieldFiles.size();indexField++){
		optData.inputBeam(indexField,setup.fieldFiles[indexField].dijFile,setup.fieldFiles[indexField].weightFile);
	}

	for(int indexStruct=0;indexStruct<setup.structureFiles.size();indexStruct++){
		optData.inputStructure(setup.structureFiles[indexStruct].name,setup.structureFiles[indexStruct].structureFile,setup.structureFiles[indexStruct].eud);
	}

	for(int indexObj=0;indexObj<setup.objectives.size();indexObj++){
		optData.inputObjective(setup.objectives[indexObj]);
	}
	/*
	vector<SConstraint> vConstrains; // add constrains 
	vConstrains = setup.objectives;

	vector<double> objFunValue;
	*/
	ptime start = boost::posix_time::microsec_clock::local_time();
	//optimization
	//vector<double> resultVWeight;

	MDopt mdOpt;
	mdOpt.optimization(&optData,setup.maxIter);

	ptime stop = boost::posix_time::microsec_clock::local_time();
	time_duration diff = stop - start;
	long milliseconds = diff.total_milliseconds();
	std::cout << milliseconds << std::endl;

	optData.getObjFunValues()->push_back(milliseconds);

	//output result data
	
	//vector<double> resultDose;
	optData.calculateDose();
	optData.outputWeight(setup.outputDir);
	optData.outputDose(setup.outputDir);
	optData.outputObjValue(setup.outputDir);
	optData.outputDVH(setup.outputDir);
	
	return 0;
}